package entity

import (
	"fmt"
	"sync"
	"sync/atomic"
)

var _ IBase = &EntityBase{}

/*
IBase 定义实体基础接口，包含实体核心属性和行为管理
方法列表：
  - String: 获取实体字符串化信息
  - 属性访问：DBID/实体ID/类型/空间ID
  - 分组管理：添加/删除/查询分组
  - 状态管理：获取/设置实体状态
  - 空间关系：获取所属实体集合
*/
type IBase interface {
	//字符串化信息
	String() string

	/* 属性 */

	/*
		GetDBID 获取当前实体关联的数据库唯一标识符
		返回值: 数据库ID(uint64类型)
	*/
	GetDBID() uint64

	/*
		GetEntityID 获取当前实体的唯一标识符
		返回值: 实体ID(uint64类型)
	*/
	GetEntityID() uint64

	/*
		GetType 获取实体类型标识符
		返回值: 实体类型描述字符串
	*/
	GetType() string

	/*
		GetSpaceID 获取实体所属空间的标识符
		返回值: 空间ID(uint64类型)
	*/
	GetSpaceID() uint64

	/*
		AddGroup 将实体添加到指定组
		参数g: 要添加的组名称(string类型)
	*/
	AddGroup(g string)

	/*
		DelGroup 将实体从指定组移除
		参数g: 要移除的组名称(string类型)
	*/
	DelGroup(g string)

	/*
		GetGroups 获取实体所属的所有组集合
		返回值: 线程安全的组集合指针(sync.Map类型)，存储格式为[组名:struct{}]
	*/
	GetGroups() *sync.Map

	/*
		GetGroup 检查实体是否属于指定组
		参数g: 要检查的组名称(string类型)
		返回值: 存在返回true，否则false
	*/
	GetGroup(g string) bool

	/*
		GetEntityState 获取当前实体状态
		返回值: 实体状态枚举值(EntityStateEnum类型)
	*/
	GetEntityState() EntityStateEnum

	/*
		SetEntityState 设置实体状态
		参数st: 要设置的状态枚举值(EntityStateEnum类型)
	*/
	SetEntityState(st EntityStateEnum)

	/*
		GetEntities 获取关联的实体集合接口
		返回值: 实体集合接口(IEntities类型)，用于批量操作关联实体
	*/
	GetEntities() IEntities
}

/*
EntityBase 实体基础结构，实现IEntityBase接口
字段说明：
  - entityType: 实体类型标识
  - entityID:   系统内唯一实体标识
  - dbid:       数据库持久化ID
  - spaceID:    所属空间标识
  - groups:     并发安全的分组集合（使用sync.Map实现）
  - state:      原子操作维护的实体状态
  - spacePtr:   指向所属实体集合的接口引用
*/
type EntityBase struct {
	/* 属性 */

	entityType string //实例对象类型
	entityID   uint64 //实例ID
	dbid       uint64 //存储ID
	spaceID    uint64 //空间ID
	groups     sync.Map

	//对象状态
	state atomic.Uint32
	//所在集合
	spacePtr IEntities
}

func (this *EntityBase) OnCreated(etype string, eid, dbid uint64, spacePtr IEntities, param ...interface{}) {
	this.entityType = etype
	this.entityID = eid
	this.dbid = dbid
	this.spacePtr = spacePtr
	this.spaceID = spacePtr.GetEntityID()
}

/*
String 生成实体描述字符串
返回格式：[Type:{类型} EntityID:{实体ID} DBID:{存储ID} SpaceID:{空间ID}]
*/
func (this *EntityBase) String() string {
	return fmt.Sprintf("[Type:%s EntityID:%d DBID:%d SpaceID:%d]",
		this.entityType, this.entityID, this.dbid, this.spaceID)
}

////////////////////////////////
//属性获取

// GetDBID 获取数据库持久化ID
func (e *EntityBase) GetDBID() uint64 {
	return e.dbid
}

// GetEntityID 获取系统内唯一实体ID
func (e *EntityBase) GetEntityID() uint64 {
	return e.entityID
}

// GetType 获取实体类型标识
func (e *EntityBase) GetType() string {
	return e.entityType
}

// GetSpaceID 获取实体所属空间ID
func (e *EntityBase) GetSpaceID() uint64 {
	return e.spaceID
}

/*
AddGroup 添加实体到指定分组
参数：
  - g: 分组名称
*/
func (e *EntityBase) AddGroup(g string) {
	e.groups.Store(g, true)
}

/*
DelGroup 从指定分组移除实体
参数：
  - g: 分组名称
*/
func (e *EntityBase) DelGroup(g string) {
	e.groups.Delete(g)
}

/*
GetGroups 获取实体所属全部分组
返回：
  - *sync.Map: 并发安全的分组集合指针（使用Load/Store方法操作）
*/
func (e *EntityBase) GetGroups() *sync.Map {
	return &e.groups
}

/*
GetGroup 检查是否属于指定分组
参数：
  - g: 分组名称

返回：
  - bool: true表示属于该分组
*/
func (e *EntityBase) GetGroup(g string) bool {
	_, ok := e.groups.Load(g)
	return ok
}

/*
GetEntityState 获取当前实体状态
返回：
  - EntityStateEnum: 使用原子操作读取的状态值
*/
func (e *EntityBase) GetEntityState() EntityStateEnum {
	return e.state.Load()
}

/*
SetEntityState 设置实体状态
参数：
  - st: 要设置的状态枚举值
*/
func (e *EntityBase) SetEntityState(st EntityStateEnum) {
	e.state.Store(st)
}

/*
GetEntities 获取实体所属集合接口
返回：
  - IEntities: 指向包含该实体的集合对象
*/
func (e *EntityBase) GetEntities() IEntities {
	return e.spacePtr
}
